Skip to content

docs(hyperframes): noventa lecciones medidas, siete herramientas de verificación y el estilo measured-light - #9

Open
occazzio wants to merge 10 commits into
nateherkai:mainfrom
occazzio:docs/lecciones-medidas-hyperframes
Open

occazzio wants to merge 10 commits into
nateherkai:mainfrom
occazzio:docs/lecciones-medidas-hyperframes

Conversation

@occazzio

@occazzio occazzio commented Sep 11, 2026

Copy link
Copy Markdown

Qué es

Usé el kit para producir piezas y medir cada afirmación contra referencias reales de motion graphics. El proceso dejó un conjunto de hallazgos que contradicen o completan lo que el skill de hyperframes ya decía, más las herramientas que sostienen esas afirmaciones y un estilo nuevo para la biblioteca.

Todo lo que se afirma en el documento está medido, no estimado.

Qué cambia

references/lecciones-medidas.md — noventa lecciones

Enlazado como primera referencia del SKILL.md, con la nota de que donde contradiga al resto del skill gana, porque está medido. Van en ocho grupos con índice, ordenados por el momento en que hacen falta: El motor · Fluidez · Composición y texto · Color, luz y fondo · Objetos y técnicas · Movimiento · Entrega y formatos · Método e instrumentos.

Lo que ya estaba:

  • Trampas del motor de captura por seek. immediateRender muerde en las dos direcciones: con el default el elemento se congela en su estado inicial desde el cuadro 0, y con false muestra su estado final desde el cuadro 0. También: los fundidos que terminan en un límite de clip necesitan un tl.set duro, no hay obturador —todo el motion blur es autoreado—, y los valores relativos (+=, -=) rompen bajo render en paralelo.
  • La escala real de un travelling. Medido cuadro a cuadro: el objeto pasa del 13 % al 88 % del ancho en 3,8 s. Un empuje de 1,0 a 1,15 no es una cámara.
  • Medición de texto. Ninguna es válida antes de document.fonts.ready: offsetWidth devuelve el ancho de la tipografía de respaldo, 23 % menor.
  • Ritmo, tiempo de lectura (17 CPS), audio y método de verificación, incluido el A/B pareado por timestamp contra la referencia.

Lo nuevo de esta tanda — material vectorial, medido produciendo una pieza contra la técnica de prompt → SVG editable → cada trazo animado:

  • Cuando el gráfico es un diagrama, un esquema o un plano, el material correcto es SVG en línea. 179 trazos son 179 nodos que GSAP alcanza. Un <img src="algo.svg"> no sirve.
  • pathLength="1" normaliza el guion. Medido: el trazo recto más corto y el más largo se llevan 59 a 1; sin normalizar, el mismo tween deja el dibujo emparchado.
  • 🚨 vector-effect: non-scaling-stroke y pathLength no conviven. El plano aparece punteado desde el cuadro cero —el stroke-dasharray: 1 vuelve a medirse en píxeles— y de paso infló la medición de fluidez de 1,45 a 2,02: el instrumento contaba el titileo como movimiento. Y vector-effect no se hereda: va en el path, no en el <svg>.
  • 🚨 En SVG, GSAP no usa transform-origin: hornea el pivote en una matriz calculada desde el bounding box. Va por svgOrigin, en coordenadas del viewBox. Sin eso un diafragma no cierra: las palas se van del cuadro.
  • 🚨 transform-box: view-box mide desde la esquina min-x min-y del viewBox, no desde (0,0). Si el viewBox arranca corrido, todo lo que gira se va a otro lado.
  • El barrido de un zoom es radial. v(r) = r · dS/dt: cero en el punto fijo, 12,4 px de σ en el borde. Un desenfoque parejo está mal en los dos lugares. Se resuelve con una capa de backdrop-filter enmascarada por un gradiente radial, hermana de lo que escala y nunca hija —si no, la máscara escala con el zoom.
  • El trazo vectorial se multiplica por la escala. A 7,5× un stroke-width de 2,6 se dibuja de 19,5 px. sw = ancho_en_pantalla / (k · escala), animado con el mismo ease que la cámara.
  • La cola de un power2.inOut mata el cuadro: 0,6 s marcados como quietos al final de un zoom de 2,85 s.
  • 🚨 Un tipeo no sostiene un plano. Un carácter de 40 px pinta ~300 píxeles sobre 2.073.600. Y la cámara sobre un cuadro vacío tampoco mueve nada. De 39 % a 13 % de cuadros quietos poniendo algo que cruce el cuadro.
  • El cursor de un tipeo se lee del layout, no se estima: un <span> por carácter y offsetLeft + offsetWidth.

scripts/lab/ — siete herramientas, con su manual

fluidez.sh mide cuántos cuadros no cambian respecto del anterior y dibuja el perfil
sfx.sh sintetiza aire/click/sub/cama/riser con el pico en una posición conocida
master.sh deja el audio en −16 LUFS verificando el pico real y corrigiéndose solo
web.sh busca el CRF más bajo que entre en el límite de subida, copiando el audio ya masterizado
recorte.py foto de producto con esquinas redondeadas, borde suavizado y alfa
logos.mjs logos de marca reales con su color oficial
getfont.mjs baja cualquier Google Font en woff2 y arma el @font-face

README.md documenta el orden en que se usan y lo que no es obvio de cada una. Arranca por ahí porque dos veces un chequeo automático inventó problemas que no existían: antes de creerle a una medición rara, verificar el instrumento.

Todo con ffmpeg, Node y Pillow.

style-library/03-measured-light/ — el registro claro

Papel #F3F4F9, tinta #0A0A14, acento #1D1DE8. El texto va negro sobre claro y el color vive únicamente en los objetos.

Los tokens no son de gusto: son umbrales medidos y están para calcular con ellos — --sostener-px-s: 60 (recorrido/duración mínimo de una cámara sobre superficie plana), --obturador: 0.9 (σ = (px_s / fps) · obturador / 3) y --lectura-cps: 17. Cuatro cartas, DESIGN.md con lo que no se hace, y el registro reconstruido: 3 estilos, 410 cartas, 0 avisos.

Correcciones a contenido existente

  • references/typography.md prohibía tipografías sin advertir que el motor sólo embebe 18 familias. Siguiendo la lista tal como estaba se podía elegir una que no está embebida y el render caía a la de respaldo en silencio.
  • references/motion-principles.md proponía animar letterSpacing como variación de entrada, y el propio lint del motor lo rechaza: reflowea el texto y se clava a píxeles enteros, así que tiembla bajo la captura por seek.
  • scripts/check-kit.mjs recorre el disco, no el índice de git. Un entorno virtual de Python local —el que pide Kokoro para el TTS— le metía 1.404 errores de archivos que nunca van al repo. Se suman .venv, .venv-tts, venv y __pycache__ a la lista de carpetas que ya salta.

Para el revisor

  • El documento está en español. Si preferís que el kit mantenga todo en inglés, lo traduzco sin problema — decímelo y lo hago en este mismo PR.
  • .claude/ y .agents/ están sincronizados con npm run sync:skills, como pide el CLAUDE.md del repo.
  • Verificado: npm run check da 711 archivos, 3 estilos, 410 cartas, 0 errores; npm run sync:skills reporta 95 archivos y 0 discrepancias.
  • Las herramientas van en scripts/lab/ y no en video-projects/, que está en .gitignore — las referencias del documento apuntan ahí.
  • Las piezas de laboratorio no se incluyen: video-projects/ está ignorado, tal como pide el CLAUDE.md del repo. El documento describe las mediciones sin depender de esos archivos.
  • El corpus de referencias de motion graphics tampoco se incluye: es material de terceros.

🤖 Generated with Claude Code

thiagovisuales and others added 9 commits September 11, 2026 00:46
… verificación

Producir ocho piezas contra un corpus de 22 referencias de motion graphics dejó
un conjunto de hallazgos que contradicen o completan lo que el skill ya decía.
Todo lo que se afirma acá está medido, no estimado.

Nuevo: references/lecciones-medidas.md
  · Las trampas del motor de captura por seek: immediateRender muerde en las dos
    direcciones (con false el elemento muestra su estado FINAL desde el cuadro 0),
    los fundidos que terminan en un límite de clip necesitan un tl.set duro, no
    hay obturador así que todo el motion blur es autoreado, y dos tweens sobre la
    misma propiedad se pisan en silencio.
  · La escala real de un travelling: medido sobre una referencia, el objeto pasa
    del 13 % al 88 % del ancho del cuadro. Un empuje de 1.0 a 1.15 no es una
    cámara. Umbral de percepción: 1 px de desplazamiento aparente por cuadro.
  · Por qué una cámara necesita textura (grano) para verse, y por qué el modo de
    fusión importa: overlay sobre negro devuelve negro.
  · Cómo se ilumina un objeto en la oscuridad: lo define su borde, no su relleno.
  · Ninguna medición de texto es válida antes de document.fonts.ready — offsetWidth
    devuelve el ancho de la tipografía de respaldo, medido 23 % menor. Alternativas
    por porcentaje y transformada que no dependen de ninguna métrica.
  · Siete layouts de composición leídos de las referencias, con el único caso en
    que corresponde centrar.
  · Ritmo (variación 3×), tiempo de lectura (17 caracteres por segundo), y las
    equivalencias de curva entre la literatura y GSAP: cubic out es power2.out,
    no power3 — la numeración de GSAP induce a este error.
  · Audio: el sonido va en el pico de la animación, y loudnorm controla el pico de
    muestra mientras el encoder AAC reconstruye picos entre muestras.

Nuevo: scripts/lab/ — cuatro herramientas que sostienen esas afirmaciones
  · fluidez.sh  mide cuántos cuadros no cambian respecto del anterior
  · sfx.sh      sintetiza aire/click/sub/cama/riser con el pico en posición conocida
  · master.sh   deja el audio en -16 LUFS verificando el pico real y corrigiéndose
  · getfont.mjs baja cualquier Google Font en woff2 y arma el @font-face

Correcciones a contenido existente
  · references/typography.md prohibía tipografías sin advertir que el motor sólo
    embebe 18 familias. Siguiendo la lista tal como estaba se podía elegir una que
    no está embebida, y el render caía a la de respaldo en silencio.
  · references/motion-principles.md proponía animar letterSpacing como variación
    de entrada, y el propio lint del motor lo rechaza: reflowea el texto y se clava
    a píxeles enteros, así que tiembla bajo la captura por seek.

Verificado: npm run check (695 archivos, 0 errores) y npm run sync:skills sin
discrepancias entre .claude/ y .agents/.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
scripts/lab/logos.mjs baja logos del CDN de Simple Icons con el color oficial de
cada marca, sin API key. Se bajan al proyecto en vez de enlazarlos porque el motor
renderiza sin red garantizada y una composición tiene que ser reproducible offline.

No todas las marcas están: Adobe, Canva, Slack y OpenAI devuelven 404 porque
pidieron que no se use su logo. La herramienta lo reporta en vez de tragárselo —
la diferencia entre notarlo y descubrir un hueco recién en el render.

Y un detalle que no es decoración: el logo va sobre una pastilla blanca. Notion,
Vercel, GitHub y OBS son casi negros y sobre fondo oscuro desaparecen.

Además, en lecciones-medidas.md: el color vive en los objetos, no en las letras.
Texto blanco sobre oscuro o negro sobre claro. Si el texto compite en color con
el objeto, hay dos cosas peleando por el mismo trabajo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Un valor relativo (+=, -=) captura su base al inicializar el tween. El render
reparte la pieza en tramos entre varios workers: uno inicializa a mitad de vuelo
del tween anterior y otro arranca en frío con el estado final, así que el mismo
cuadro sale en dos posiciones distintas y se ve como un salto en el límite del
tramo. Va siempre fromTo con extremos explícitos.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Kokoro corre sobre onnxruntime >= 1.20.1, que pide Python >= 3.10. El venv
.venv-tts pesa 160 MB y se recrea en un comando; no va al repo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`recorte.py` deja una foto de producto con esquinas redondeadas, borde
suavizado y alfa: sin alfa no hay reflejo ni sombra que siga la silueta y la
foto se lee como estampilla pegada.

`web.sh` busca el CRF más bajo que entre en el límite de subida copiando el
audio ya masterizado. El render del motor sale a ~17 Mbps, mucho más de lo
necesario.

`README.md` documenta las siete, el orden en que se usan y —lo que importa—
lo que no es obvio de cada una. Dos veces un chequeo automático inventó
problemas que no existían, así que el manual arranca por ahí: antes de creerle
a una medición rara, verificar el instrumento.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tercer estilo de la biblioteca: papel #F3F4F9, tinta #0A0A14, acento #1D1DE8.
El texto va negro sobre claro y el color vive únicamente en los objetos.

Los tokens no son de gusto, son umbrales medidos y están para calcular con
ellos: --sostener-px-s 60 (recorrido/duración mínimo de una cámara sobre
superficie plana), --obturador 0.9 (σ = (px_s / fps) · obturador / 3) y
--lectura-cps 17.

Cuatro cartas —cifra de takeover, tesis, lista y rótulo— más DESIGN.md con lo
que NO se hace. Un campo claro sin rango tonal no le da nada a la cámara: las
manchas van con alfa alto y fuera de la banda de lectura.

Registro reconstruido: 3 estilos, 410 cartas, 0 avisos.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Las ochenta anteriores estaban en una lista plana. Ahora van en ocho grupos con
índice, ordenados por el momento en que hacen falta: El motor · Fluidez ·
Composición y texto · Color, luz y fondo · Objetos y técnicas · Movimiento ·
Entrega y formatos · Método e instrumentos.

Diez nuevas, todas medidas produciendo lab-40-vector contra la técnica de
Quiver Arrow 2 (prompt → SVG editable → cada trazo animado):

- Cuando el gráfico es un diagrama, un esquema o un plano, el material correcto
  es SVG en línea: 179 trazos son 179 nodos que GSAP alcanza.
- pathLength="1" normaliza el guion. Medido: el trazo recto más corto y el más
  largo se llevan 59 a 1; sin normalizar, el mismo tween deja el dibujo
  emparchado.
- vector-effect:non-scaling-stroke y pathLength no conviven — el plano aparece
  punteado desde el cuadro cero, y además infló la medición de fluidez de 1,45
  a 2,02. Y vector-effect no se hereda: va en el path.
- En SVG, GSAP no usa transform-origin: hornea el pivote en una matriz. Va por
  svgOrigin, en coordenadas del viewBox. Sin eso un diafragma no cierra.
- transform-box:view-box mide desde la esquina min-x/min-y del viewBox.
- El barrido de un zoom es radial: v(r) = r · dS/dt, cero en el punto fijo y
  12,4 px de σ en el borde. Una capa de backdrop-filter con máscara radial,
  hermana de lo que escala, nunca hija.
- El trazo vectorial se multiplica por la escala: a 7,5× un 2,6 se dibuja de
  19,5 px. sw = ancho_en_pantalla / (k · escala), animado con el mismo ease
  que la cámara.
- La cola de un power2.inOut mata el cuadro: 0,6 s marcados como quietos al
  final de un zoom de 2,85 s.
- Un tipeo no sostiene un plano —un carácter de 40 px pinta 0,015 % del
  cuadro— y la cámara sobre un cuadro vacío tampoco. Hace falta algo que
  cruce. De 39 % a 13 % de cuadros quietos.
- El cursor de un tipeo se lee del layout, no se estima: un span por carácter y
  offsetLeft + offsetWidth.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
npm run sync:skills, como pide el CLAUDE.md del repo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Dos cosas que `npm run check` encontró:

- El enlace desde SKILL.md al manual del lab tenía un nivel de menos. Desde
  `.claude/skills/hyperframes/` hacen falta tres `..` para llegar a la raíz,
  no dos: con dos apuntaba a `.claude/scripts/lab/README.md`.
- `check-kit.mjs` recorre el disco, no el índice de git. Un entorno virtual de
  Python local —el que pide Kokoro para el TTS— le mete 1.404 errores de
  archivos que nunca van al repo. Se suman `.venv`, `.venv-tts`, `venv` y
  `__pycache__` a la lista de carpetas que ya salta.

`npm run check`: 711 archivos, 3 estilos, 410 cartas, 0 errores.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@occazzio occazzio changed the title docs(hyperframes): lecciones medidas contra un corpus de referencias, y cuatro herramientas de verificación docs(hyperframes): noventa lecciones medidas, siete herramientas de verificación y el estilo measured-light Sep 18, 2026
…n mal

Auditoría de esta hoja contra lo que el motor publica hoy. El kit pinea
0.7.109; la versión publicada es 0.8.46, del mismo día, y el repo saca varias
por día. Dos afirmaciones de acá habían envejecido y una hipótesis mía era
directamente falsa.

CORREGIDO · "No hay obturador: todo el motion blur es autoreado".
Hay dos mecanismos reales. El componente del catálogo
(`npx hyperframes add motion-blur`) corre dentro de la página, reposiciona la
línea de tiempo en tiempos sub-cuadro y apila copias con plus-lighter: el
promedio ES la integral del obturador. Lee la matriz transform resuelta, así
que cubre traslación, escala, rotación, 3D y sesgo — o sea que cubre el ZOOM,
que es donde la fórmula a mano no llega. A/B pareado en el pico de un zoom a
7,5×: 9,10 de energía de detalle con mi backdrop-filter radial contra 11,63 con
el componente (1,28×), pagando 18 s de render contra 3 m 16 s (10,6×). Con 6
muestras, 1 m 9 s y visualmente indistinguible a esta longitud de estela.
Y el instrumento miente: con menos muestras el laplaciano da MÁS detalle porque
cuenta el escalón de la estela, así que hubo que mirar el cuadro ampliado.
El motor tiene además su propio obturador desde 0.8.45, que no está en la
versión del kit.

CORREGIDO · la lección del tipeo. Yo suponía que el `tl.call` de la skill
oficial no sobrevivía a la captura por seek. Medido con un A/B a 4 workers:
sobrevive. Las dos recetas sirven. La diferencia real es otra y no la tenía:
con spans los caracteres invisibles siguen ocupando lugar, así que un cursor
en línea se para después de la palabra completa desde el cuadro cero.

NUEVO · `--variables` + `--batch`: una composición, N videos, con manifest.
Medido en la versión del kit: 3 filas, 3,6 s por video. Es lo que convierte una
pieza en una tanda.

NUEVO · las salidas que no son MP4 —mov/webm con alfa, png-sequence,
--resolution 4k— todas ya disponibles y ninguna estaba acá.

NUEVO · mirar la versión antes de creerle a esta hoja, y leer las 21 skills que
el repo publica en skills/ antes de inventar. Una lección de acá las mejora
(pathLength="1", que río arriba todavía no usa) y otra salió de que ellas me
corrigieran a mí.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants